/*
 * $Id: string_compar.c,v 1.4 2005-12-28 11:47:30 bacon Exp $
 */

#if defined(__MSTRING)
#include <xp/bas/mstring.h>
#elif defined(__WSTRING)
#include <xp/bas/mstring.h>
#else
#include <xp/bas/string.h>
#endif

#include <xp/bas/ctype.h>

int xp_strcmp (const xp_char_t* s1, const xp_char_t* s2)
{
	while (*s1 == *s2 && *s2 != XP_CHAR('\0')) s1++, s2++;
	if (*s1 > *s2) return 1;
	else if (*s1 < *s2) return -1;
	return 0;
}

int xp_strcmpn (const xp_char_t* s1, const xp_char_t* s2, xp_size_t n)
{
	if (n == 0) return 0;

	while (--n > 0 && *s1 != XP_CHAR('\0') && *s1 == *s2) s1++, s2++;
	if (*s1 > *s2) return 1;
	else if (*s1 < *s2) return -1;
	return 0;
}

int xp_strxcmp (const xp_char_t* s1, xp_size_t len, const xp_char_t* s2)
{
	const xp_char_t* end = s1 + len;
	while (s1 < end && *s2 != XP_CHAR('\0') && *s1 == *s2) {
		s1++; s2++;
	}
	if (s1 == end && *s2 == XP_CHAR('\0')) return 0;
	if (*s1 == *s2) return (s1 < end)? 1: -1;
	return (*s1 > *s2)? 1: -1;
}

int xp_strxncmp (
	const xp_char_t* s1, xp_size_t len1, 
	const xp_char_t* s2, xp_size_t len2)
{
	const xp_char_t* end1 = s1 + len1;
	const xp_char_t* end2 = s2 + len2;

	while (s1 < end1 && s2 < end2 && *s1 == *s2) {
		s1++; s2++;
	}
	if (s1 == end1 && s2 == end2) return 0;
	if (*s1 == *s2) return (s1 < end1)? 1: -1;
	return (*s1 > *s2)? 1: -1;
}


int xp_strcasecmp (const xp_char_t* s1, const xp_char_t* s2)
{
	xp_char_t c1, c2;

	c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	while (c1 == c2 && c2 != XP_CHAR('\0')) {
		s1++, s2++;
		c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	}

	if (c1 > c2) return 1;
	else if (c1 < c2) return -1;
	return 0;
}

int xp_strcasecmpn (const xp_char_t* s1, const xp_char_t* s2, xp_size_t n)
{
	xp_char_t c1, c2;
	if (n == 0) return 0;

	do {
		c1 = xp_toupper(*s1);
		c2 = xp_toupper(*s2);

		if (c1 == XP_CHAR('\0') || c1 != c2) break;
		s1++; s2++;
	} while (--n > 0);

	if (c1 > c2) return 1;
	else if (c1 < c2) return -1;
	return 0;
}

int xp_strncasecmp (const xp_char_t* s1, const xp_char_t* s2, xp_size_t count)
{
	xp_char_t c1, c2;
	if (count == 0) return 0;

	c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	while (--count && c1 != XP_CHAR('\0') && c1 == c2) {
		s1++, s2++;
		c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	}
	if (c1 > c2) return 1;
	else if (c1 < c2) return -1;
	return 0;
}

int xp_strxcasecmp (const xp_char_t* s1, xp_size_t len, const xp_char_t* s2)
{
	xp_char_t c1, c2;
	const xp_char_t* end = s1 + len;

	c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	while (s1 < end && c2 != XP_CHAR('\0') && c1 == c2) {
		s1++; s2++;
		c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	}
	if (s1 == end && c2 == XP_CHAR('\0')) return 0;
	if (c1 == c2) return (s1 < end)? 1: -1;
	return (c1 > c2)? 1: -1;
}

int xp_strxncasecmp (
	const xp_char_t* s1, xp_size_t len1, const xp_char_t* s2, xp_size_t len2)
{
	xp_char_t c1, c2;
	const xp_char_t* end1 = s1 + len1;
	const xp_char_t* end2 = s2 + len2;

	c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	while (s1 < end1 && s2 < end2 && c1 == c2) {
		s1++; s2++;
		c1 = xp_toupper(*s1); c2 = xp_toupper(*s2);
	}
	if (s1 == end1 && s2 == end2) return 0;
	if (c1 == c2) return (s1 < end1)? 1: -1;
	return (c1 > c2)? 1: -1;
}

